﻿using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;

namespace JX.Infrastructure.Common
{
	/// <summary>
	/// 常用扩展
	/// </summary>
    public static class CommonExtensions
    {
		#region 数据类型转换

		#region 转换为布尔值类型
		/// <summary>
		/// 转换为布尔值类型,输入为true,1,yes 时返回true,其他字符均返回false
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static bool ToBoolean(this object data)
		{
			return DataConverter.CBoolean(data);
		}
		/// <summary>
		/// 转换为布尔值类型,输入为true,1,yes 时返回true,其他字符均返回false
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static bool ToBoolean(this string data)
		{
			return DataConverter.CBoolean(data);
		}
		#endregion

		#region 转换为日期
		/// <summary>
		/// 转换为日期，失败返回当前系统日期
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static DateTime ToDateTime(this object data)
		{
			return DataConverter.CDate(data);
		}
		/// <summary>
		/// 转换为日期，失败返回默认日期
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static DateTime ToDateTime(this object data, DateTime defaultValue)
		{
			return DataConverter.CDate(data, defaultValue);
		}
		/// <summary>
		/// 转换为日期，失败返回当前系统日期
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static DateTime ToDateTime(this string data)
		{
			return DataConverter.CDate(data);
		}
		/// <summary>
		/// 转换为日期，失败返回默认日期
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static DateTime ToDateTime(this string data, DateTime defaultValue)
		{
			return DataConverter.CDate(data, defaultValue);
		}
		#endregion

		#region 转换为可空日期
		/// <summary>
		/// 转换为日期，失败返回当前系统日期
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static DateTime? ToDateTimeOrNull(this object data)
		{
			return DataConverter.CDateOrNull(data);
		}
		/// <summary>
		/// 转换为日期，失败返回默认日期
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static DateTime? ToDateTimeOrNull(this object data, DateTime? defaultValue)
		{
			return DataConverter.CDateOrNull(data, defaultValue);
		}
		/// <summary>
		/// 转换为日期，失败返回当前系统日期
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static DateTime? ToDateTimeOrNull(this string data)
		{
			return DataConverter.CDateOrNull(data);
		}
		/// <summary>
		/// 转换为日期，失败返回默认日期
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static DateTime? ToDateTimeOrNull(this string data, DateTime? defaultValue)
		{
			return DataConverter.CDateOrNull(data, defaultValue);
		}
		#endregion

		#region 转换为整数
		/// <summary>
		/// 转换为整数
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static int ToInt32(this object data,int defaultValue = 0)
		{
			return DataConverter.CLng(data, defaultValue);
		}
		/// <summary>
		/// 转换为整数
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static int ToInt32(this string data, int defaultValue = 0)
		{
			return DataConverter.CLng(data, defaultValue);
		}
		/// <summary>
		/// 转换为整数
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static int ToInt32(this decimal data, int defaultValue = 0)
		{
			return DataConverter.CLng(data, defaultValue);
		}
		/// <summary>
		/// 转换为整数
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static int ToInt32(this double data, int defaultValue = 0)
		{
			return DataConverter.CLng(data, defaultValue);
		}
		/// <summary>
		/// 转换为整数
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static int ToInt32(this float data, int defaultValue = 0)
		{
			return DataConverter.CLng(data, defaultValue);
		}
		#endregion

		#region 转换为decimal
		/// <summary>
		/// 转换为decimal
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static decimal ToDecimal(this object data, decimal defaultValue = 0)
		{
			return DataConverter.CDecimal(data, defaultValue);
		}
		/// <summary>
		/// 转换为decimal
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static decimal ToDecimal(this string data, decimal defaultValue = 0)
		{
			return DataConverter.CDecimal(data, defaultValue);
		}
		/// <summary>
		/// 转换为decimal，保留2位小数，四舍五入。
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static decimal ToDecimalRound(this object data, decimal defaultValue = 0)
		{
			return DataConverter.CDecimal(data, defaultValue, 2, MidpointRounding.AwayFromZero);
		}
		/// <summary>
		/// 转换为decimal，保留2位小数，四舍五入。
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static decimal ToDecimalRound(this string data, decimal defaultValue = 0)
		{
			return DataConverter.CDecimal(data, defaultValue, 2, MidpointRounding.AwayFromZero);
		}
		#endregion

		#region 转换为double
		/// <summary>
		/// 转换为double
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static double ToDouble(this object data, double defaultValue = 0.0)
		{
			return DataConverter.CDouble(data, defaultValue);
		}
		/// <summary>
		/// 转换为double
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static double ToDouble(this string data, double defaultValue = 0.0)
		{
			return DataConverter.CDouble(data, defaultValue);
		}
		#endregion

		#region 转换为float
		/// <summary>
		/// 转换为float
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static float ToSingle(this object data, float defaultValue = 0f)
		{
			return DataConverter.CSingle(data, defaultValue);
		}
		/// <summary>
		/// 转换为float
		/// </summary>
		/// <param name="data"></param>
		/// <param name="defaultValue">转换不成功时提供的默认值</param>
		/// <returns></returns>
		public static float ToSingle(this string data, float defaultValue = 0f)
		{
			return DataConverter.CSingle(data, defaultValue);
		}
		#endregion

		#region 转换为Guid
		/// <summary>
		/// 转换为Guid
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static Guid ToGuid(this object data)
		{
			return DataConverter.ToGuid(data);
		}
		/// <summary>
		/// 转换为Guid
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static Guid ToGuid(this string data)
		{
			return DataConverter.ToGuid(data);
		}

		/// <summary>
		/// 转换为可空Guid
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static Guid? ToGuidOrNull(this object data)
		{
			return DataConverter.ToGuidOrNull(data);
		}
		/// <summary>
		/// 转换为可空Guid
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static Guid? ToGuidOrNull(this string data)
		{
			return DataConverter.ToGuidOrNull(data);
		}

		/// <summary>
		/// 转换为可空Guid
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static List<Guid> ToGuidList(this string data)
		{
			return DataConverter.ToGuidList(data);
		}
		#endregion

		#region 转换为char
		/// <summary>
		/// 转换为char，失败返回char.MinValue
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static char ToChar(this object data)
		{
			return DataConverter.ToChar(data);
		}
		/// <summary>
		/// 转换为char，失败返回char.MinValue
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		public static char ToChar(this string data)
		{
			return DataConverter.ToChar(data);
		}
		#endregion

		#endregion

		#region 泛型转换/DataTable转换
		/// <summary>
		/// 泛型转换
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="data"></param>
		/// <returns></returns>
		public static T To<T>(this object data)
		{
			return DataConverter.To<T>(data);
		}

		/// <summary>
		/// 把DataTable转换成IList《T》
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="table"></param>
		/// <returns></returns>
		public static IList<T> ToList<T>(this DataTable table) where T : new()
		{
			var propts = typeof(T).GetProperties();
			var rtnList = new List<T>();
			T model;
			object val;
			foreach (DataRow row in table.Rows)
			{
				model = new T();
				foreach (var l in propts)
				{
					try
					{
						val = row[l.Name];
					}
					catch
					{
						continue;
					}
					if (val == DBNull.Value)
					{
						l.SetValue(model, null);
					}
					else
					{
						l.SetValue(model, val);
					}
				}
				rtnList.Add(model);
			}
			return rtnList;
		}
		/// <summary>
		/// 把IList《T》转换成DataTable
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="list"></param>
		/// <returns></returns>
		public static DataTable ToDataTable<T>(this IList<T> list)
		{
			if (list == null || list.Count <= 0)
			{
				return new DataTable();
			}
			DataTable dt = new DataTable(typeof(T).Name);
			DataColumn column;
			DataRow row;
			PropertyInfo[] myPropertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
			foreach (T t in list)
			{
				if (t == null)
				{
					continue;
				}
				row = dt.NewRow();
				for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
				{
					PropertyInfo pi = myPropertyInfo[i];
					string name = pi.Name;
					if (!dt.Columns.Contains(name) || dt.Columns[name] == null)
					{
						column = new DataColumn(name, pi.PropertyType);
						dt.Columns.Add(column);
					}
					row[name] = pi.GetValue(t, null);
				}
				dt.Rows.Add(row);
			}
			return dt;
		}
		#endregion

		#region 排序
		/// <summary>
		/// 对List排序。例：ListSort("Name","desc");
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="data"></param>
		/// <param name="field"></param>
		/// <param name="rule"></param>
		public static void ListSort<T>(this IList<T> data, string field, string rule) where T : new()
		{
			List<T> result = new List<T>(data);
			result.ListSort(field, rule);
		}
		/// <summary>
		/// 对List排序。例：ListSort("Name","desc");
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="data"></param>
		/// <param name="field"></param>
		/// <param name="rule"></param>
		public static void ListSort<T>(this List<T> data, string field, string rule) where T : new()
		{
			if (!string.IsNullOrEmpty(rule) && (rule.ToLower().Equals("desc") || rule.ToLower().Equals("asc")))
			{
				data.Sort(
						delegate (T info1, T info2)
						{
							Type t = typeof(T);
							PropertyInfo pro = t.GetProperty(field);
							return rule.ToLower().Equals("asc") ?
									  pro.GetValue(info1, null).ToString().CompareTo(pro.GetValue(info2, null).ToString()) :
									  pro.GetValue(info2, null).ToString().CompareTo(pro.GetValue(info1, null).ToString());
						});
			}
		}
		#endregion

		#region HttpRequest扩展
		/// <summary>
		/// 得到User-Agent的值
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string UserAgent(this HttpRequest request)
		{
			return request.Headers[HeaderNames.UserAgent];
		}

		/// <summary>
		/// 得到Referer的值
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string UrlReferrer(this HttpRequest request)
		{
			return request.Headers[HeaderNames.Referer];
		}

		/// <summary>
		/// 得到当前请求的完整URL
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string AbsoluteUri(this HttpRequest request)
		{
			return new StringBuilder()
				.Append(request.Scheme)
				.Append("://")
				.Append(request.Host)
				.Append(request.PathBase)
				.Append(request.Path)
				.Append(request.QueryString)
				.ToString();
		}
		#endregion
	}
}
